﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 public class AStar:MonoBehaviour
 {
     private Map map;//地图信息

     void Awake()
     {
         map = GetComponent<Map>();
     }

     /// <summary>
     /// 计算路径
     /// </summary>
     /// <param name="startPos"></param>
     /// <param name="endPos"></param>
     public List<Node> FindingPath(Vector2 startPos, Vector2 endPos)
     {
         //Debug.Log(string.Format("坐标轴X{0},Y{1}", startPos, endPos));
         Node startNode = map.GetNodeByPos(startPos);
         Node endNode = map.GetNodeByPos(endPos);
         //Debug.Log(string.Format("获取到开始Node:{0},结束Node{1}", startNode.x+","+startNode.y, endNode.x+","+endNode.y));
         List<Node> openSet=new List<Node>();
         HashSet<Node> closeSet=new HashSet<Node>();
         openSet.Add(startNode);

         while (openSet.Count > 0)
         {
             //Debug.Log("还在检测1当中");
             Node currentNode = openSet[0];
             for (int i = 0; i < openSet.Count; i++)
             {
                 if (openSet[i].fConst < currentNode.fConst ||
                     openSet[i].fConst == currentNode.fConst && openSet[i].hConst < currentNode.hConst)
                 {
                     currentNode = openSet[i];
                 }
             }

             openSet.Remove(currentNode);
             closeSet.Add(currentNode);

             if (currentNode == endNode)
             {
                 //Debug.Log("寻路检查完毕");
                 return GeneratePath(startNode, currentNode);
             }

             foreach (var node in GetNeibourhood(currentNode))
             {
                 //Debug.Log("遍历中");
                 if ((!node.canWalk&&!node.isMonster)||  closeSet.Contains(node))
                 {
                     //Debug.Log("canwalk:"+node.canWalk+":isin:"+closeSet.Contains(node));
                     //Debug.Log(node.isMonster+"==="+node.pos+"---"+endPos);
                     //Debug.Log("这个节点是墙或者怪物或者在闭合节点里面");
                     continue;
                 }
                 //if (closeSet.Contains(node)) continue;
                 int newCost = currentNode.gConst + GetDistanceNodes(currentNode, node);
                 if (newCost < node.gConst || !openSet.Contains(node))
                 {
                     node.gConst = newCost;
                     node.hConst = GetDistanceNodes(node, endNode);
                     node.parent = currentNode;
                     if (!openSet.Contains(node))
                     {
                         openSet.Add(node);
                     }
                 }
             }
         }
         return null;
     }

     /// <summary>
     /// 获取路径
     /// </summary>
     /// <param name="start"></param>
     /// <param name="end"></param>
     List<Node> GeneratePath(Node start, Node end)
     {
         //Debug.Log("进入确定path");
         List<Node> path=new List<Node>();
         Node temp = end;
         while (temp!=start)
         {
             path.Add(temp);
             temp = temp.parent;
         }
         path.Reverse();
         return path;
         //map.PathReslut(path);
     }

     /// <summary>
     /// 获取四周node，当前只需要获取前后左右四个点
     /// </summary>
     /// <param name="node"></param>
     /// <returns></returns>
    public List<Node> GetNeibourhood(Node node)
     {
         //Debug.Log("开始查找格子四周，格子："+map.GetIndexByXY(node.x,node.y));
         List<Node> list=new List<Node>();
         list.Add(map.nodes[node.x - 1, node.y]);
         list.Add(map.nodes[node.x +1, node.y]);
         list.Add(map.nodes[node.x, node.y-1]);
         list.Add(map.nodes[node.x , node.y+1]);
         return list;
     }

     /// <summary>
     /// 根据两个坐标获取之间的距离
     /// </summary>
     /// <param name="start"></param>
     /// <param name="end"></param>
     /// <returns></returns>
     int GetDistanceNodes(Node start,Node end)
     {
         int x = Mathf.Abs(end.x - start.x);
         int y = Mathf.Abs(end.y - start.y);
         if (x > y)
         {
             return y*14 + (x - y)*10;
         }
         else
         {
             return x * 14 + (y- x) * 10;
         }
     }
 }

